﻿using System.IO;
using System.Runtime.Serialization.Json;
using System.ServiceModel.Channels;
using System.Text;
using System.Xml;

namespace UFIDA.U9.WSS.ProxyService.Utils
{
    /// <summary>
    ///     消息帮助类
    /// </summary>
    public static class MessageHelper
    {
        /// <summary>
        ///     获取消息的内容格式
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static WebContentFormat GetContentFormat(Message message)
        {
            if (!message.Properties.ContainsKey(WebBodyFormatMessageProperty.Name)) return WebContentFormat.Default;
            WebBodyFormatMessageProperty bodyFormat =
                (WebBodyFormatMessageProperty) message.Properties[WebBodyFormatMessageProperty.Name];
            return bodyFormat.Format;
        }

        /// <summary>
        ///     读取Message Raw Body
        /// </summary>
        /// <param name="message"></param>
        /// <param name="isCreateNewMessage"></param>
        /// <returns></returns>
        public static byte[] ReadRawBody(ref Message message, bool isCreateNewMessage = true)
        {
            if (message.IsEmpty) return null;
            byte[] bodyBytes;
            using (XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents())
            {
                bodyReader.ReadStartElement("Binary");
                bodyBytes = bodyReader.ReadContentAsBase64();
            }

            if (!isCreateNewMessage) return bodyBytes;
            //复制消息
            MemoryStream ms = new MemoryStream();
            XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(ms);
            writer.WriteStartElement("Binary");
            writer.WriteBase64(bodyBytes, 0, bodyBytes.Length);
            writer.WriteEndElement();
            writer.Flush();
            ms.Position = 0;
            XmlDictionaryReader reader =
                XmlDictionaryReader.CreateBinaryReader(ms, XmlDictionaryReaderQuotas.Max);
            Message newMessage = Message.CreateMessage(reader, int.MaxValue, message.Version);
            newMessage.Properties.CopyProperties(message.Properties);
            newMessage.Headers.CopyHeadersFrom(message);
            message = newMessage;
            //关闭后，Message存在问题，具体原因不明
            //reader.Close();
            //writer.Close();
            //ms.Close();
            return bodyBytes;
        }

        /// <summary>
        ///     获取Message内容
        /// </summary>
        /// <param name="message"></param>
        /// <param name="isCreateNewMessage"></param>
        /// <returns></returns>
        public static string GetContent(ref Message message, bool isCreateNewMessage = true)
        {
            if (message.IsEmpty) return string.Empty;
            WebContentFormat messageFormat = GetContentFormat(message);
            switch (messageFormat)
            {
                case WebContentFormat.Raw:
                    return GetRawContent(ref message, isCreateNewMessage);
                case WebContentFormat.Json:
                    return GetJsonContent(ref message, isCreateNewMessage);
                default:
                    return GetDefaultContent(ref message, isCreateNewMessage);
            }
        }

        /// <summary>
        ///     获取Default Message内容
        /// </summary>
        /// <param name="message"></param>
        /// <param name="isCreateNewMessage"></param>
        /// <returns></returns>
        public static string GetDefaultContent(ref Message message, bool isCreateNewMessage = true)
        {
            MemoryStream ms = new MemoryStream();
            XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(ms);
            message.WriteMessage(writer);
            writer.Flush();
            string messageBody = Encoding.UTF8.GetString(ms.ToArray());
            if (string.IsNullOrEmpty(messageBody)) return messageBody;
            if (!isCreateNewMessage) return messageBody;
            // Here would be a good place to change the message body, if so desired.
            // now that the message was read, it needs to be recreated.
            ms.Position = 0;
            // if the message body was modified, needs to reencode it, as show below
            // ms = new MemoryStream(Encoding.UTF8.GetBytes(messageBody));
            XmlDictionaryReader reader =
                XmlDictionaryReader.CreateTextReader(ms, XmlDictionaryReaderQuotas.Max);
            Message newMessage = Message.CreateMessage(reader, int.MaxValue, message.Version);
            newMessage.Properties.CopyProperties(message.Properties);
            newMessage.Headers.CopyHeadersFrom(message);
            message = newMessage;
            return messageBody;
        }

        /// <summary>
        ///     获取Raw Message内容
        /// </summary>
        /// <param name="message"></param>
        /// <param name="isCreateNewMessage">是否创建新的Message</param>
        /// <returns></returns>
        public static string GetRawContent(ref Message message, bool isCreateNewMessage = true)
        {
            byte[] bodyBytes = ReadRawBody(ref message, isCreateNewMessage);
            if (bodyBytes == null) return string.Empty;
            return Encoding.UTF8.GetString(bodyBytes);
        }

        /// <summary>
        ///     获取Default Message内容
        /// </summary>
        /// <param name="message"></param>
        /// <param name="isCreateNewMessage"></param>
        /// <returns></returns>
        public static string GetJsonContent(ref Message message, bool isCreateNewMessage = true)
        {
            MemoryStream ms = new MemoryStream();
            XmlDictionaryWriter writer = JsonReaderWriterFactory.CreateJsonWriter(ms);
            message.WriteMessage(writer);
            writer.Flush();
            string messageBody = Encoding.UTF8.GetString(ms.ToArray());
            if (string.IsNullOrEmpty(messageBody)) return messageBody;
            if (!isCreateNewMessage) return messageBody;
            // Here would be a good place to change the message body, if so desired.
            // now that the message was read, it needs to be recreated.
            ms.Position = 0;
            // if the message body was modified, needs to reencode it, as show below
            // ms = new MemoryStream(Encoding.UTF8.GetBytes(messageBody));
            XmlDictionaryReader reader =
                JsonReaderWriterFactory.CreateJsonReader(ms, XmlDictionaryReaderQuotas.Max);
            Message newMessage = Message.CreateMessage(reader, int.MaxValue, message.Version);
            newMessage.Properties.CopyProperties(message.Properties);
            newMessage.Headers.CopyHeadersFrom(message);
            message = newMessage;
            return messageBody;
        }
    }
}